#include <iostream>
#include <stdint.h>
#include <vector>
#include "coroutineAsm.h"
#include "../logger/logger.h"

extern "C" void swap_context(void *, void *) asm("swap_context");
asm(R"(
swap_context:
  mov 0x00(%rsp), %rdx
  lea 0x08(%rsp), %rcx
  mov %r12, 0x00(%rdi)
  mov %r13, 0x08(%rdi)
  mov %r14, 0x10(%rdi)
  mov %r15, 0x18(%rdi)
  mov %rdx, 0x20(%rdi)
  mov %rcx, 0x28(%rdi)
  mov %rbx, 0x30(%rdi)
  mov %rbp, 0x38(%rdi)
  mov 0x00(%rsi), %r12
  mov 0x08(%rsi), %r13
  mov 0x10(%rsi), %r14
  mov 0x18(%rsi), %r15
  mov 0x20(%rsi), %rax
  mov 0x28(%rsi), %rcx
  mov 0x30(%rsi), %rbx
  mov 0x38(%rsi), %rbp
  mov %rcx, %rsp
  jmpq *%rax
)");




// 线程对应的主协程的生命周期归mainCoroutine管理
// 线程结束时, mainCoroutine变量销毁, 其管理的主协程堆内存也销毁
thread_local TinyRPC::CoroutineAsmPtr mainCoroutineAsm = nullptr;

// 线程对应的当前活跃协程， 但是其并不控制当前活跃协程的生命周期， 只是记录一下
thread_local TinyRPC::CoroutineAsmPtr currentCoroutineAsm = nullptr;




namespace TinyRPC{


CoroutineAsm::CoroutineAsm(CoroutineTask coroutineTask, int stackSize)
: m_stackSize(stackSize)
,  m_coroutineTask(coroutineTask){
    GetMainCoroutine();
    m_mem.resize(stackSize);
    m_stack = (char *)((uintptr_t)(&m_mem.back()) & ~15ull) - sizeof(void *);
    m_context.reg[4] = (void *)CoroutineAsm::CoroutineFunc;
    m_context.reg[5] = m_stack;
   
}

Registers& CoroutineAsm::getContext(){
    return m_context;
}
CoroutineAsm::CoroutineAsm(){
}

CoroutineAsm::~CoroutineAsm(){
    std::cout<<"CoroutineAsm del"<<std::endl;
}
// 进入协程
void CoroutineAsm::resume(){
    currentCoroutineAsm = this->shared_from_this();
    swap_context(&mainCoroutineAsm->m_context, &m_context);
    currentCoroutineAsm = mainCoroutineAsm;
}



//退出线程
void CoroutineAsm::Yield(){
    swap_context(&currentCoroutineAsm->m_context, &mainCoroutineAsm->m_context);
}
void CoroutineAsm::setName(const std::string& name){
    m_name = name;
}
std::string CoroutineAsm::getName(){
    return m_name;
}



bool CoroutineAsm::InMain(){
return mainCoroutineAsm == nullptr ||
        mainCoroutineAsm == currentCoroutineAsm;
}
bool CoroutineAsm::InCoroutine(){
return currentCoroutineAsm != nullptr  &&
        currentCoroutineAsm != mainCoroutineAsm;
}
void CoroutineAsm::makeSureInMain(){
    if(mainCoroutineAsm == nullptr){
        GetMainCoroutine();
    }
    if(!CoroutineAsm::InMain()){
        LOG_ERROR<<"coroutine must call by main thread, donot support call by another coroutine";
        exit(1);
    }
}

void CoroutineAsm::GetMainCoroutine(){
    if(mainCoroutineAsm == nullptr){
        mainCoroutineAsm = CoroutineAsmPtr(new CoroutineAsm);
        currentCoroutineAsm = mainCoroutineAsm;
    }
}

std::shared_ptr<CoroutineAsm> CoroutineAsm::CurrentCoroutine(){
    return currentCoroutineAsm;
}


// 协程的执行入口， 里面执行用户的函数
void CoroutineAsm::CoroutineFunc(){
    currentCoroutineAsm->runTask();
    // 跑完用户任务, 释放任务
    currentCoroutineAsm->m_coroutineTask = nullptr;
    // 切换到主线程
    swap_context(&currentCoroutineAsm->getContext(), &mainCoroutineAsm->getContext());
    
}

}
